package ace.module.account.core.impl.service.impl;

import ace.cmp.core.constants.CoreConstant;
import ace.cmp.id.generator.api.LongIdGenerator;
import ace.module.account.api.constant.IamAccountConstant;
import ace.module.account.api.enums.IamAccountPassportPassportTypeEnum;
import ace.module.account.api.enums.IamAccountProfileRegisterSourceFromEnum;
import ace.module.account.api.enums.IamAccountProfileSexEnum;
import ace.module.account.api.enums.IamAccountStatusEnum;
import ace.module.account.api.enums.IamAccountTagTypeEnum;
import ace.module.account.api.enums.IamApplicationStatusEnum;
import ace.module.account.api.model.config.IamApplicationCaptchaSmsAppConfig;
import ace.module.account.core.impl.constant.AccountCoreConstant;
import ace.module.account.core.impl.dao.entity.IamAccount;
import ace.module.account.core.impl.dao.entity.IamAccountPassport;
import ace.module.account.core.impl.dao.entity.IamAccountPassword;
import ace.module.account.core.impl.dao.entity.IamAccountProfile;
import ace.module.account.core.impl.dao.entity.IamAccountTag;
import ace.module.account.core.impl.dao.entity.IamApplication;
import ace.module.account.core.impl.dao.entity.IamApplicationConfig;
import ace.module.account.core.impl.dao.repository.IamAccountPassportRepository;
import ace.module.account.core.impl.dao.repository.IamAccountPasswordRepository;
import ace.module.account.core.impl.dao.repository.IamAccountProfileRepository;
import ace.module.account.core.impl.dao.repository.IamAccountRepository;
import ace.module.account.core.impl.dao.repository.IamAccountTagRepository;
import ace.module.account.core.impl.dao.repository.IamApplicationConfigRepository;
import ace.module.account.core.impl.dao.repository.IamApplicationRepository;
import ace.module.account.core.impl.manager.IamApplicationConfigManager;
import ace.module.account.core.impl.properties.AccountCoreProperties;
import ace.module.account.core.impl.service.IamAccountInitService;
import ace.module.captcha.sms.api.constant.CaptchaSmsConstant;
import ace.module.common.api.constant.CommonConstants;
import ace.module.common.api.constant.SystemRoleConstants;
import ace.module.common.core.impl.properties.ModuleCommonSecurityProperties;
import ace.module.tenant.api.constant.TenantConstant;
import java.time.Instant;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

/**
 * @author caspar
 * @date 2023/3/30 16:59
 */
@AllArgsConstructor
@Component
@Slf4j
public class IamAccountInitServiceImpl implements IamAccountInitService {

  private final LongIdGenerator idGenerator;
  private final IamApplicationRepository iamApplicationRepository;
  private final IamAccountRepository iamAccountRepository;
  private final IamAccountProfileRepository iamAccountProfileRepository;
  private final IamAccountPasswordRepository iamAccountPasswordRepository;
  private final IamAccountPassportRepository iamAccountPassportRepository;
  private final IamAccountTagRepository iamAccountTagRepository;
  private final IamApplicationConfigRepository iamApplicationConfigRepository;
  private final IamApplicationConfigManager iamApplicationConfigManager;
  private final PasswordEncoder passwordEncoder;
  private final AccountCoreProperties accountCoreProperties;
  private final ModuleCommonSecurityProperties moduleCommonSecurityProperties;

  @Transactional(rollbackFor = Exception.class)
  @Override
  public void init() {

    this.addPlatformAppData();

    this.addMemberAppData();


  }

  private void addMemberAppData() {
    if (iamApplicationRepository.existsById(IamAccountConstant.DEFAULT_MEMBER_IAM_APP_ID)) {
      log.info("会员账户应用数据已经存在，所以忽略初始化");
      return;
    }
    IamApplication iamApplication =
        IamApplication.builder()
            .id(IamAccountConstant.DEFAULT_MEMBER_IAM_APP_ID)
            .name("会员账户应用")
            .key(IamAccountConstant.DEFAULT_MEMBER_IAM_APP_ID.toString())
            .outId(TenantConstant.DEFAULT_TENANT_ID.toString())
            .outType(SystemRoleConstants.MEMBER)
            .status(IamApplicationStatusEnum.NORMAL.getCode())
            .remark("会员账户应用")
            .deleteFlag(CoreConstant.DELETE_FLAG_NOT)
            .createTime(Instant.now().toEpochMilli())
            .updateTime(Instant.now().toEpochMilli())
            .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
            .build();

    IamAccount iamAccount =
        IamAccount.builder()
            .id(IamAccountConstant.DEFAULT_MEMBER_IAM_ACCOUNT_ID)
            .iamAppId(iamApplication.getId())
            .status(IamAccountStatusEnum.NORMAL.getCode())
            .passwordChangeRequired(false)
            .deleteFlag(CoreConstant.DELETE_FLAG_NOT)
            .createTime(Instant.now().toEpochMilli())
            .updateTime(Instant.now().toEpochMilli())
            .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
            .build();

    IamAccountPassport iamAccountPassport =
        IamAccountPassport.builder()
            .id(idGenerator.get())
            .iamAppId(iamApplication.getId())
            .iamAccountId(iamAccount.getId())
            .passport(moduleCommonSecurityProperties.getAdministratorUsername())
            .passport2("")
            .passport3("")
            .passportType(IamAccountPassportPassportTypeEnum.USERNAME.getCode())
            .deleteFlag(CoreConstant.DELETE_FLAG_NOT)
            .createTime(Instant.now().toEpochMilli())
            .updateTime(Instant.now().toEpochMilli())
            .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
            .build();

    IamAccountPassword iamAccountPassword =
        IamAccountPassword.builder()
            .id(idGenerator.get())
            .iamAppId(iamApplication.getId())
            .iamAccountId(iamAccount.getId())
            .password(passwordEncoder.encode(AccountCoreConstant.DEFAULT_MEMBER_ACCOUNT_PASSWORD))
            .deleteFlag(CoreConstant.DELETE_FLAG_NOT)
            .createTime(Instant.now().toEpochMilli())
            .updateTime(Instant.now().toEpochMilli())
            .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
            .build();

    IamAccountPassport iamAccountPassportPhone =
        IamAccountPassport.builder()
            .id(idGenerator.get())
            .iamAppId(iamApplication.getId())
            .iamAccountId(iamAccount.getId())
            .passport(moduleCommonSecurityProperties.getAdministratorUsername())
            .passport2("")
            .passport3("")
            .passportType(IamAccountPassportPassportTypeEnum.PHONE.getCode())
            .deleteFlag(CoreConstant.DELETE_FLAG_NOT)
            .createTime(Instant.now().toEpochMilli())
            .updateTime(Instant.now().toEpochMilli())
            .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
            .build();

    IamAccountProfile iamAccountProfile =
        IamAccountProfile.builder()
            .id(idGenerator.get())
            .iamAppId(iamApplication.getId())
            .iamAccountId(iamAccount.getId())
            .avatar(accountCoreProperties.getDefaultAvatarUrl())
            .birthday(Instant.now().toEpochMilli())
            .nickName("默认会员")
            .realName("默认会员")
            .sex(IamAccountProfileSexEnum.UNKNOWN.getCode())
            .registerSourceFrom(IamAccountProfileRegisterSourceFromEnum.PC.getCode())
            .signature("signature")
            .deleteFlag(CoreConstant.DELETE_FLAG_NOT)
            .createTime(Instant.now().toEpochMilli())
            .updateTime(Instant.now().toEpochMilli())
            .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
            .build();

    IamAccountTag iamAccountTag =
        IamAccountTag.builder()
            .id(idGenerator.get())
            .iamAppId(iamApplication.getId())
            .iamAccountId(iamAccount.getId())
            .key(SystemRoleConstants.MEMBER)
            .value(StringUtils.EMPTY)
            .type(IamAccountTagTypeEnum.SYSTEM.getCode())
            .deleteFlag(CoreConstant.DELETE_FLAG_NOT)
            .createTime(Instant.now().toEpochMilli())
            .updateTime(Instant.now().toEpochMilli())
            .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
            .build();

    this.iamAccountRepository.insert(iamAccount, false);
    this.iamAccountProfileRepository.insert(iamAccountProfile, false);
    this.iamAccountPasswordRepository.insert(iamAccountPassword, false);
    this.iamAccountPassportRepository.insert(iamAccountPassport, false);
    this.iamAccountPassportRepository.insert(iamAccountPassportPhone, false);
    this.iamApplicationRepository.insert(iamApplication, false);
    this.iamAccountTagRepository.insert(iamAccountTag, false);
    log.info("初始化会员账户应用数据成功");
  }

  private void addPlatformAppData() {
    if (iamApplicationRepository.existsById(moduleCommonSecurityProperties.getIamAdminPlatformAppId())) {
      log.info("平台账户应用数据已经存在，所以忽略初始化");
      return;
    }
    IamApplication iamApplication = IamApplication.builder()
        .id(IamAccountConstant.DEFAULT_ADMIN_IAM_APP_ID)
        .name(CommonConstants.DEFAULT_TITLE)
        .key(CommonConstants.DEFAULT_APP_KEY)
        .status(IamApplicationStatusEnum.NORMAL.getCode())
        .remark(CommonConstants.DEFAULT_REMARK)
        .deleteFlag(CoreConstant.DELETE_FLAG_NOT)
        .createTime(Instant.now().toEpochMilli())
        .updateTime(Instant.now().toEpochMilli())
        .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
        .build();

    IamAccount iamAccount = IamAccount.builder()
        .id(IamAccountConstant.DEFAULT_ADMIN_ADMINISTRATOR_ACCOUNT_ID)
        .iamAppId(iamApplication.getId())
        .status(IamAccountStatusEnum.NORMAL.getCode())
        .passwordChangeRequired(false)
        .deleteFlag(CoreConstant.DELETE_FLAG_NOT)
        .createTime(Instant.now().toEpochMilli())
        .updateTime(Instant.now().toEpochMilli())
        .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
        .build();

    IamAccountPassport iamAccountPassport = IamAccountPassport.builder()
        .id(CommonConstants.DEFAULT_APP_ID)
        .iamAppId(iamApplication.getId())
        .iamAccountId(iamAccount.getId())
        .passport(moduleCommonSecurityProperties.getAdministratorUsername())
        .passport2("")
        .passport3("")
        .passportType(IamAccountPassportPassportTypeEnum.USERNAME.getCode())
        .deleteFlag(CoreConstant.DELETE_FLAG_NOT)
        .createTime(Instant.now().toEpochMilli())
        .updateTime(Instant.now().toEpochMilli())
        .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
        .build();

    IamAccountPassport iamAccountPhonePassport = IamAccountPassport.builder()
        .id(idGenerator.get())
        .iamAppId(iamApplication.getId())
        .iamAccountId(iamAccount.getId())
        .passport(moduleCommonSecurityProperties.getAdministratorPhone())
        .passport2("")
        .passport3("")
        .passportType(IamAccountPassportPassportTypeEnum.PHONE.getCode())
        .deleteFlag(CoreConstant.DELETE_FLAG_NOT)
        .createTime(Instant.now().toEpochMilli())
        .updateTime(Instant.now().toEpochMilli())
        .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
        .build();

    IamAccountPassword iamAccountPassword = IamAccountPassword.builder()
        .id(CommonConstants.DEFAULT_APP_ID)
        .iamAppId(iamApplication.getId())
        .iamAccountId(iamAccount.getId())
        .password(passwordEncoder.encode(moduleCommonSecurityProperties.getAdministratorPassword()))
        .deleteFlag(CoreConstant.DELETE_FLAG_NOT)
        .createTime(Instant.now().toEpochMilli())
        .updateTime(Instant.now().toEpochMilli())
        .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
        .build();

    IamAccountProfile iamAccountProfile = IamAccountProfile.builder()
        .id(CommonConstants.DEFAULT_APP_ID)
        .iamAppId(iamApplication.getId())
        .iamAccountId(iamAccount.getId())
        .avatar("")
        .birthday(Instant.now().toEpochMilli())
        .nickName("超级管理员")
        .realName("超级管理员")
        .sex(IamAccountProfileSexEnum.UNKNOWN.getCode())
        .registerSourceFrom(IamAccountProfileRegisterSourceFromEnum.PC.getCode())
        .signature("超级管理员")
        .deleteFlag(CoreConstant.DELETE_FLAG_NOT)
        .createTime(Instant.now().toEpochMilli())
        .updateTime(Instant.now().toEpochMilli())
        .rowVersion(CoreConstant.DEFAULT_ROW_VERSION)
        .build();

    IamApplicationConfig iamApplicationConfig = this.iamApplicationConfigManager.createBuilder(
            IamApplicationCaptchaSmsAppConfig.builder()
                .captchaSmsAppId(CaptchaSmsConstant.OPERATOR_PLATFORM_SMS_APPLICATION_ID)
                .build()
        )
        .iamAppId(iamApplication.getId())
        .key(IamAccountConstant.CONFIG_KEY_PHONE_CAPTCHA_SMS)
        .name("关联短信验证应用配置")
        .build();

    this.iamAccountRepository.insert(iamAccount, false);
    this.iamAccountProfileRepository.insert(iamAccountProfile, false);
    this.iamAccountPasswordRepository.insert(iamAccountPassword, false);
    this.iamAccountPassportRepository.insert(iamAccountPassport, false);
    this.iamAccountPassportRepository.insert(iamAccountPhonePassport, false);
    this.iamApplicationRepository.insert(iamApplication, false);
    this.iamApplicationConfigRepository.insert(iamApplicationConfig, false);

    log.info("初始化平台账户应用数据成功");
  }
}
